package xs.szw.service.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.transaction.annotation.Transactional;
import xs.szw.common.constant.SecurityConstants;
import xs.szw.common.constant.SystemConstant;
import xs.szw.common.exception.BusinessException;
import xs.szw.common.model.Option;
import xs.szw.common.utils.BeanUtils;
import xs.szw.service.converter.RoleConverter;
import xs.szw.service.model.vo.RoleVo;
import xs.szw.service.model.dto.RoleDto;
import xs.szw.service.mapper.RoleMenuMapper;
import xs.szw.service.mapper.UserRoleMapper;
import xs.szw.service.model.pojo.sys.Role;
import xs.szw.service.model.pojo.sys.RoleMenu;
import xs.szw.service.model.pojo.sys.UserRole;
import xs.szw.service.service.RoleService;
import xs.szw.service.mapper.RoleMapper;
import org.springframework.stereotype.Service;
import xs.szw.service.utils.SecurityUtils;

import java.util.List;
import java.util.Set;

/**
* @author asus
* @description 针对表【sys_role(角色表)】的数据库操作Service实现
* @createDate 2025-02-10 18:37:27
*/
@Service
@RequiredArgsConstructor
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role>
        implements RoleService{


    private final RoleMapper roleMapper;


    private final RoleMenuMapper roleMenuMapper;


    private final UserRoleMapper userRoleMapper;

    private final RoleConverter roleConverter;

    /**
     * 创建角色
     * @param roleDto 包含新角色信息的DTO。
     * @return
     */
    @Override
    public void createRole(RoleDto roleDto) {
        //1.校验
        validateRoleForCreateOrUpdate(null,roleDto.getRoleName(),roleDto.getRoleCode());
        //2.执行sql
        Role role = BeanUtils.toBean(roleDto, Role.class);
        this.save(role);

    }

    /**
     * 修改角色
     * @param roleDto 包含要更新的角色信息的DTO。
     * @return
     */
    @Override
    public boolean updateRole(RoleDto roleDto) {
        //1.校验
        validateRoleForCreateOrUpdate(roleDto.getId(),roleDto.getRoleName(),roleDto.getRoleCode());
        //2.执行sql
        Role role = BeanUtils.toBean(roleDto, Role.class);
       return this.updateById(role);

    }

    /**
     * 删除角色
     * @param id 要删除的角色的ID。
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean deleteRoleWithRelations(Long id) {
        //1.校验
        validateRoleExists(id);
        //2.执行sql
        //2.1删除role角色数据以及user_role、role_menu角色相关数据
        int d = roleMapper.deleteById(id);
        //user_role
        LambdaQueryWrapper<UserRole> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserRole::getRoleId,id);
        int d1 = userRoleMapper.delete(queryWrapper);
        //role_menu
        LambdaQueryWrapper<RoleMenu> queryWrapper1 = new LambdaQueryWrapper<>();
        queryWrapper1.eq(RoleMenu::getRoleId,id);
        int d2 = roleMenuMapper.delete(queryWrapper1);
        if(d > 0 && d1 > 0 && d2 > 0){
            return true;
        }else{
            return false;
        }
    }

    /**
     *根据ID获取角色的详细信息
     * @param id 要获取的角色的ID。
     * @return
     */
    @Override
    public RoleVo getRole(Long id) {
        //1.校验
        validateRoleExists(id);
        //2.执行sql
        Role r = this.getById(id);
        RoleVo roleVo = BeanUtils.toBean(r, RoleVo.class);
        return roleVo;

    }

    /**
     * 获取角色分页列表
     * @param current
     * @param size
     * @param roleName
     * @return
     */
    @Override
    public Page<RoleVo> getRolePage(Integer current, Integer size,String roleName) {
        //构建LambdaQueryWrapper
        LambdaQueryWrapper<Role> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(Role::getName,roleName);
        //获取分页对象
        Page page = new Page<>(current, size);
        Page<Role> resultPage  = this.page(page,queryWrapper);
        // 将查询结果转换为 RoleVo 列表
        List<RoleVo> roleVoList = BeanUtil.copyToList(resultPage.getRecords(), RoleVo.class);
//        List<RoleVo> roleVoList = resultPage.getRecords().stream().map(RoleVo::new).collect(Collectors.toList());
        return new Page<RoleVo>(resultPage.getCurrent(),resultPage.getSize(),resultPage.getTotal()).setRecords(roleVoList);

    }

    /**
     * 获取角色下拉列表
     * @return
     */
    @Override
    public List<Option<Long>> getRoleList() {
        List<Role> list = this.list(new LambdaQueryWrapper<Role>()
                .ne(!SecurityUtils.isRoot(), Role::getCode, SystemConstant.ROOT_ROLE_CODE)
                .select(Role::getId, Role::getName)
                .orderByAsc(Role::getSort)
        );

        return roleConverter.roleListToOptionList(list);
    }

    /**
     * 获取角色列表
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean deleteBatchRoleWithRelations(List<Long> ids) {
        //1.校验
        ids.stream().forEach(id->validateRoleExists(id));
        //批量删除role角色 role_menu user_role关系记录
        this.removeBatchByIds(ids);
        int d = roleMenuMapper.delete((new LambdaQueryWrapper<RoleMenu>().in(RoleMenu::getRoleId, ids)));
        int d1 = userRoleMapper.delete((new LambdaQueryWrapper<UserRole>().in(UserRole::getRoleId, ids)));
        if(d > 0 && d1 > 0){
            return true;
        } else{
            return false;
        }

    }

    /**
     * 获取最大范围的数据权限
     * @param roles
     * @return
     */
    @Override
    public Integer getMaximumDataScope(Set<String> roles) {
        Integer dataScope = roleMapper.getMaximumDataScope(roles);
        return dataScope;
    }

    private void validateRoleForCreateOrUpdate(Long id, String name, String code) {
        // 校验自己存在
        validateRoleExists(id);
        // 校验角色名的唯一性
        validateRoleNameUnique(id, name);
        // 校验岗位编码的唯一性
        validateRoleCodeUnique(id, code);
    }

    private void validateRoleNameUnique(Long id, String name) {
        LambdaQueryWrapper<Role> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Role::getName,name);
        Role ro = this.getOne(wrapper);
        if (ro == null) {
            return;
        }
        // 如果 id 为空，说明不用比较是否为相同 id 的岗位
        //id==null 抛出异常
        Assert.notNull(id,"创建:角色名重复！");
        if (!ro.getId().equals(id)) {
            throw new BusinessException("更新:数据库已有角色名!");
        }
    }

    private void validateRoleCodeUnique(Long id, String code) {
        LambdaQueryWrapper<Role> roleLambdaQueryWrapper = new LambdaQueryWrapper<>();
        roleLambdaQueryWrapper.eq(Role::getName,code);
        Role ro = this.getOne(roleLambdaQueryWrapper);
        if (ro == null) {
            return;
        }
        // 如果 id 为空，说明不用比较是否为相同 id 的岗位
        //id==null 抛出异常 参数校验用Assert断言
        Assert.notNull(id,"创建:角色编码重复！");

        if(!ro.getId().equals(id)){
            throw new BusinessException("更新:数据库已有角色编码!");
        }
    }

    private void validateRoleExists(Long id) {
        if (id == null) {
            return;
        }
        if(this.getById(id)==null){
            throw new BusinessException("校验:角色不存在！");
        }
    }
}




